﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface IUsuarioRepository : IRepository<Usuario>
    {
        IList<Usuario> FindAllFiltro(string apellido, string _usuario);
        int GetLogin(Usuario usuario);
        Usuario FindByUsuarioPassword(string usuario, string password);
    }

    public class UsuarioRepository : IUsuarioRepository
    {
        protected readonly IDbConnection _db;

        public UsuarioRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Usuario> FindAll()
        {
            const string query = "SELECT * FROM USUARIOS";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Usuario>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Usuario> Find(System.Linq.Expressions.Expression<Func<Usuario, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Usuario FindById(int id)
        {
            const string query = "SELECT * FROM USUARIOS " +
                    "WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Usuario>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Add(Usuario newEntity)
        {
            const string query = "INSERT INTO USUARIOS (FECHA_REGISTRO, ROL_ID, DOCUMENTO, APELLIDO, NOMBRES, " +
                        "USUARIO, PASSWORD, ACTIVO) VALUES (@fecha_registro, @rol_id, @documento, @apellido, " +
                        "@nombres, @usuario, @password, @activo)";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        fecha_registro = newEntity.fecha_registro,
                        rol_id = newEntity.rol_id,
                        documento = newEntity.documento,
                        apellido = newEntity.apellido,
                        nombres = newEntity.nombres,
                        usuario = newEntity.usuario,
                        password = newEntity.password,
                        activo = newEntity.activo
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            const string query = "UPDATE USUARIOS SET ACTIVO = 0 " +
                                "WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { id = id });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Modify(Usuario entity)
        {
            const string query = "UPDATE USUARIOS SET ROL_ID = @rol_id, DOCUMENTO = @documento, APELLIDO = @apellido, " +
                "NOMBRES = @nombres, USUARIO = @usuario, PASSWORD = @password, ACTIVO = @activo " +
                "WHERE ID = @id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        rol_id = entity.rol_id,
                        documento = entity.documento,
                        apellido = entity.apellido,
                        nombres = entity.nombres,
                        usuario = entity.usuario,
                        password = entity.password,
                        activo = entity.activo,
                        id = entity.id
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Usuario> FindAllFiltro(string apellido, string _usuario)
        {
            const string query = "SELECT * FROM USUARIOS " +
                "INNER JOIN ROLES ON ROLES.ID = USUARIOS.ROL_ID " +
                "WHERE ((USUARIOS.APELLIDO LIKE CONCAT('%', @apellido, '%')) OR (@apellido IS NULL)) " +
                "AND ((USUARIOS.USUARIO LIKE CONCAT('%', @usuario, '%')) OR (@usuario IS NULL))";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Usuario, Rol, Usuario>(query, (usuario, rol) =>
                    {
                        usuario.rol = rol;
                        return usuario;
                    }, new { apellido = apellido, usuario = _usuario }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public int GetLogin(Usuario usuario)
        {
            const string query = "SELECT COUNT(*) FROM USUARIOS " +
                "WHERE USUARIO = @usuario AND PASSWORD = @password";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<int>(query, new
                    {
                        usuario = usuario.usuario,
                        password = usuario.password
                    }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public Usuario FindByUsuarioPassword(string usuario, string password)
        {
            const string query = "SELECT * FROM USUARIOS " +
                "WHERE USUARIO = @usuario AND PASSWORD = @password";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Usuario>(query, new
                    {
                        usuario = usuario,
                        password = password
                    }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }
    }
}
